对象 | 对象子类型

Author Avatar
wanglinzhizhi Mar 18, 2017

对象

  1. 对象子类型. JavaScript 中有许多特殊的对象子类型, ->复杂基本类型
  2. 函数 就是对象的一个子类型.(从技术上说就是”可调用的对象”),JavaScript中的函数是”一等公民”, 因为他们本质上和普通对象一样(只是可以调用). 所以可以向操作其他对象一样操作函数(比如当做另一个函数的参数)
  3. 数组也是对象的一种类型, 具备一些额外的行为. 数组中的内容的组织方式比一般的对象要稍微复杂一些.

内置对象

JavaScript的 一些对象子类型, 通常称为 内置对象. 有些内置对象的名字看起来和简单基础类型一样

  1. String
  2. Number
  3. Boolean
  4. Object
  5. Function
  6. Array
  7. Date
  8. RegExp
  9. Error

这些内置对象从表现形式来说很像其他语言中的类型(type)或者类(clas), 比如Java的String类

但是在JavaScript中,它们实际上只是一些内置函数. 这些内置函数可以当做构造函数(由new产生的函数调用)来使用. 从而可以构造一个对应子类型的新对象.

原始值’I am a string ‘ 并不是一个对象, 他只是一个字面量, 并且是一个不可变的值. 如果要在这个字面量上执行一些操作, 比如获取长度, 访问其中某个字符等, 那需要将其转换为String对象.

幸好, 在必要的时候语言会自动把字符串字面量转换为一个String对象,也就是说不需要你显示的创建一个对象.

var strPrimitive="I am a string"
console.log(strPrimitive.length)
console.log(strPrimitive.charAt(3))

我们可以直接在字符串字面量上访问属性或者方法, 之所以可以这样做, 是因为引擎自动把字面量转换成String对象,所以可以访问属性和方法.

Note

nullundfined 没有对应的构造形式, 它们只有文字形式. 相反, Date只有构造, 没有文字形式

对于Object , Array , Function, RegExp(正则表达式)来说, 无论使用文字形式还是构造函数形式, 他们都是对象,不是字面量.

在某些情况下, 相比用文字形式创建对象,构造形式可以提供一些额外的选项. 由于这两种形式都可以创建对象,所以我们首选更简单的文字形式. 建议只在需要哪些额外选项时使用构造形式.

Error对象很少在代码中显示创建, 一般是在抛出异常时被自动创建.

对象的内容

对象的内容是由一些存储在特定命名位置的(任意类型的)值组成的.

属性描述符

var myObject = {
a: 2
}
Object.getOwnPropertyDescriptor(myObject, "a");
/**
* output
*
*
{
value: 2,
writable: true,
enumerable: true,
configurable: true
}
*/
var myObject2={}
Object.defineProperties(myObject2,"a",{
value:2,
writable:true,
configurable:true,
enumerable:true
})
myObject.a;


var myObject3={}
Object.defineProperties(myObject3,"a",{
value:2,
writable:false,
configurable:true,
enumerable:true
})
myObject3.a; /*2*/
myObject3.a=3;
myObject3.a;/*2*/
{
'use stict'
var myObject4 = {}
Object.defineProperties(myObject4, "a", {
value: 2,
writable: false,
configurable: true,
enumerable: true
})
myObject4.a; /*2*/
myObject4.a = 3;
myObject4.a; /* TypeError*/
}

TypeError 错误表示我们无法修改一个不可写的属性

对象属性值的存在性判断

如果myObject.a的属性访问返回值可能是undefined, 但是这个值有可能是属性中存储的undefined, 也有可能是因为属性不存在所以返回undefined.

那么如何区分这两种情况呢?

我们可以在不访问属性值的情况下判断对象中是否存在这个属性.

var myObject = {
a: 2
}
("a" in myObject);/*true*/
('b' in myObject);/*fasle*/
myObject.hasOwnProperty("a")/*true*/
myObject.hasOwnProperty("b")/*fasle*/

in 操作符会检查属性 是否在对象及其[[prototype]]原型链中.

相比之下,hasOwnProperty(..)只会检查属性是否在myObject中,不检查原型链([[prototype]]链)

所有的普通对象都可以通过对于Object.prototype 的委托来访问hasOwnProperty(…).

但是有的对象可以没有连接到Object.prototype (通过cerete(null)创建的对象) .

在这种情况下, 使用myObject.hasOwnProperty(..) 就会失败.

这时可以采用一种更加强硬的方法来判断:

Object.prototype.hasOwnProperty.call(myObject,"a")

它借用基础的 hasOwnProperty(..) 并把它显示的绑定到myObject上.

判断是否可枚举

  • prorertyIsEnumerable(..) 会检查给定的属性名是否直接存在于对象中(而不是原型链)并满足enumerable:true
  • Object.keys(..) 会返回一个数组,包含所有可枚举属性.
  • Object.getOwnPropertyNames(…) 会返回一个数组, 包含所有属性, 无论它们是否可枚举.

in 和 hasOwnProperty(..) 的区别在于是否查找[[prototype]]链,

Object.keys(..) 和Object.getOwnPropertyNames(..) 都会查找对象直接包含的 属性

属性不一定包含值,它们有可能是具备getter/setter 是 访问描述符






你不知道的JavaScript(上卷) 读书笔记

by wanglinzhizhi